<!DOCTYPE html>
<html>
<head>
    <title>Michelson Interferometer</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        canvas {
            border: 1px solid #ccc;
            background-color: white;
        }
    </style>
</head>
<body>
    <canvas id="michelsonCanvas" width="850" height="500"></canvas>
    <script>
        const canvas = document.getElementById('michelsonCanvas');
        const ctx = canvas.getContext('2d');

        // Helper function to draw an arrow at the end of a line
        function drawArrow(ctx, fromX, fromY, toX, toY, size = 5) {
            const angle = Math.atan2(toY - fromY, toX - fromX);
            ctx.moveTo(toX, toY);
            ctx.lineTo(toX - size * Math.cos(angle - Math.PI / 6), toY - size * Math.sin(angle - Math.PI / 6));
            ctx.moveTo(toX, toY);
            ctx.lineTo(toX - size * Math.cos(angle + Math.PI / 6), toY - size * Math.sin(angle + Math.PI / 6));
        }
        
        // Helper to draw a double arrow line
        function drawDoubleArrow(ctx, x1, y1, x2, y2, size = 5){
            ctx.beginPath();
            ctx.moveTo(x1,y1);
            ctx.lineTo(x2,y2);
            drawArrow(ctx, x1, y1, x2, y2, size);
            drawArrow(ctx, x2, y2, x1, y1, size);
            ctx.stroke();
        }

        // Main drawing function
        function drawDiagram() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.strokeStyle = 'black';
            ctx.fillStyle = 'black';
            ctx.lineWidth = 1.5;
            ctx.font = '20px serif';

            // Coordinates
            const bs_x = 220;
            const bs_y = 250;
            const m1_x = 70;
            const m2_y = 120;
            const s_y = 380;
            const lens_x = 350;
            const lens_h = 50;
            const xy_plane_x = 520;
            const focus_region_half_width = 100;
            const pattern_cx = 740;
            const pattern_cy = 250;

            // --- Draw Components ---
            
            // Mirror M1
            ctx.save();
            ctx.fillStyle = '#cccccc';
            ctx.lineWidth = 2;
            ctx.fillRect(m1_x - 4, bs_y - 40, 8, 80);
            ctx.strokeRect(m1_x - 4, bs_y - 40, 8, 80);
            ctx.fillStyle = 'black';
            ctx.fillText('M₁', m1_x - 10, bs_y - 50);
            ctx.restore();

            // Mirror M2
            ctx.save();
            const m2_w = 80;
            const m2_h = 8;
            const alpha = 7 * Math.PI / 180; // exaggerated for visibility
            ctx.translate(bs_x, m2_y);
            ctx.rotate(-alpha);
            ctx.fillStyle = '#cccccc';
            ctx.lineWidth = 2;
            ctx.fillRect(-m2_w / 2, -m2_h / 2, m2_w, m2_h);
            ctx.strokeRect(-m2_w / 2, -m2_h / 2, m2_w, m2_h);
            ctx.restore();
            ctx.fillText('M₂', bs_x + 30, m2_y - 15);

            // Beam Splitter BS
            ctx.save();
            ctx.lineWidth = 4;
            ctx.beginPath();
            ctx.moveTo(bs_x - 45, bs_y + 45);
            ctx.lineTo(bs_x + 45, bs_y - 45);
            ctx.stroke();
            ctx.restore();
            ctx.fillText('BS', bs_x + 30, bs_y + 40);

            // Source S
            ctx.save();
            ctx.fillStyle = '#666666';
            ctx.lineWidth = 2;
            ctx.fillRect(bs_x - 12, s_y, 24, 15);
            ctx.strokeRect(bs_x - 12, s_y, 24, 15);
            ctx.fillStyle = 'black';
            ctx.fillText('S', bs_x - 5, s_y + 40);
            ctx.restore();

            // Lens L
            ctx.lineWidth = 2;
            ctx.beginPath();
            ctx.moveTo(lens_x, bs_y - lens_h);
            ctx.lineTo(lens_x, bs_y + lens_h);
            drawArrow(ctx, lens_x, bs_y - lens_h + 2, lens_x, bs_y - lens_h - 2, 8);
            drawArrow(ctx, lens_x, bs_y + lens_h - 2, lens_x, bs_y + lens_h + 2, 8);
            ctx.stroke();
            ctx.fillText('L', lens_x - 5, bs_y + lens_h + 25);
            ctx.lineWidth = 1.5;

            // --- Draw Light Paths ---
            ctx.beginPath();
            // S to BS
            ctx.moveTo(bs_x, s_y);
            ctx.lineTo(bs_x, bs_y);
            drawArrow(ctx, bs_x, bs_y + 20, bs_x, bs_y, 8);
            // BS to M1
            ctx.moveTo(bs_x, bs_y);
            ctx.lineTo(m1_x + 4, bs_y);
            drawArrow(ctx, bs_x - 20, bs_y, m1_x + 4, bs_y, 8);
            // M1 to BS
            ctx.moveTo(m1_x + 4, bs_y);
            ctx.lineTo(bs_x, bs_y);
            drawArrow(ctx, m1_x + 20, bs_y, bs_x, bs_y, 8);
            // BS to M2
            ctx.moveTo(bs_x, bs_y);
            ctx.lineTo(bs_x, m2_y + 4);
            drawArrow(ctx, bs_x, bs_y - 20, bs_x, m2_y + 4, 8);
            // M2 to BS
            ctx.moveTo(bs_x, m2_y + 4);
            ctx.lineTo(bs_x, bs_y);
            drawArrow(ctx, bs_x, m2_y + 20, bs_x, bs_y, 8);
            ctx.stroke();

            // Beams after BS to Focus
            ctx.beginPath();
            const beam_start_x = bs_x + 10;
            const beam_y_sep_at_lens = 30;
            const focus_x = xy_plane_x + 80;
            const focus_y = bs_y;
            // Upper ray
            ctx.moveTo(beam_start_x, bs_y-5);
            ctx.bezierCurveTo(beam_start_x + 30, bs_y - 10, lens_x - 30, bs_y - beam_y_sep_at_lens, lens_x, bs_y - beam_y_sep_at_lens);
            drawArrow(ctx, lens_x-60, bs_y - 21, lens_x-50, bs_y-22.5, 6);
            ctx.bezierCurveTo(lens_x + 30, bs_y - beam_y_sep_at_lens, focus_x - 50, focus_y - 5, focus_x, focus_y);
            drawArrow(ctx, focus_x-60, focus_y-2, focus_x-50, focus_y-1, 6);
            // Lower ray
            ctx.moveTo(beam_start_x, bs_y+5);
            ctx.bezierCurveTo(beam_start_x + 30, bs_y + 10, lens_x - 30, bs_y + beam_y_sep_at_lens, lens_x, bs_y + beam_y_sep_at_lens);
            drawArrow(ctx, lens_x-60, bs_y + 21, lens_x-50, bs_y+22.5, 6);
            ctx.bezierCurveTo(lens_x + 30, bs_y + beam_y_sep_at_lens, focus_x - 50, focus_y + 5, focus_x, focus_y);
            drawArrow(ctx, focus_x-60, focus_y+2, focus_x-50, focus_y+1, 6);
            ctx.stroke();

            // Main z-axis
            ctx.beginPath();
            ctx.moveTo(bs_x, bs_y);
            ctx.lineTo(focus_x + 100, bs_y);
            drawArrow(ctx, focus_x + 90, bs_y, focus_x + 100, bs_y, 8);
            ctx.stroke();
            ctx.fillText('z', focus_x + 80, bs_y - 10);

            // --- Draw Annotations ---

            // Angle alpha
            ctx.save();
            ctx.beginPath();
            ctx.setLineDash([3, 3]);
            ctx.moveTo(bs_x - 40, m2_y);
            ctx.lineTo(bs_x + 40, m2_y);
            ctx.stroke();
            ctx.restore();
            ctx.beginPath();
            ctx.arc(bs_x-35, m2_y, 25, 0, -alpha-0.05, true);
            drawArrow(ctx, bs_x - 35 + 25 * Math.cos(-alpha+0.1), m2_y + 25 * Math.sin(-alpha+0.1), bs_x - 35 + 25 * Math.cos(-alpha), m2_y + 25 * Math.sin(-alpha), 6);
            ctx.stroke();
            ctx.fillText('α', bs_x - 45, m2_y - 15);
            
            // z1, z2
            drawDoubleArrow(ctx, m1_x + 4, bs_y + 20, bs_x, bs_y + 20);
            ctx.fillText('z₁', (m1_x + bs_x) / 2 - 5, bs_y + 18);
            drawDoubleArrow(ctx, bs_x + 20, m2_y + 4, bs_x + 20, bs_y);
            ctx.fillText('z₂', bs_x + 25, (m2_y + bs_y) / 2);

            // Da (aperture diameter)
            ctx.save();
            ctx.beginPath();
            ctx.moveTo(lens_x + 25, bs_y - lens_h);
            ctx.lineTo(lens_x + 15, bs_y - lens_h);
            ctx.moveTo(lens_x + 25, bs_y + lens_h);
            ctx.lineTo(lens_x + 15, bs_y + lens_h);
            drawArrow(ctx, lens_x+20, bs_y-lens_h+5, lens_x+20, bs_y-lens_h, 6);
            drawArrow(ctx, lens_x+20, bs_y+lens_h-5, lens_x+20, bs_y+lens_h, 6);
            ctx.moveTo(lens_x+20, bs_y-lens_h);
            ctx.lineTo(lens_x+20, bs_y+lens_h);
            ctx.stroke();
            ctx.fillText('Dₐ', lens_x + 28, bs_y + 5);
            ctx.restore();
            
            // x,y plane
            ctx.beginPath();
            ctx.moveTo(xy_plane_x, bs_y - 80);
            ctx.lineTo(xy_plane_x, bs_y + 80);
            drawArrow(ctx, xy_plane_x, bs_y - 70, xy_plane_x, bs_y - 80, 8);
            ctx.stroke();
            ctx.fillText('x,y', xy_plane_x + 10, bs_y - 85);

            // Δz (localization depth)
            const dz_start = lens_x + 50;
            const dz_end = focus_x + 40;
            ctx.save();
            ctx.setLineDash([5, 5]);
            ctx.beginPath();
            ctx.moveTo(dz_start, bs_y - 60);
            ctx.lineTo(dz_start, bs_y + 60);
            ctx.moveTo(dz_end, bs_y - 60);
            ctx.lineTo(dz_end, bs_y + 60);
            ctx.stroke();
            ctx.restore();
            drawDoubleArrow(ctx, dz_start, bs_y + 70, dz_end, bs_y + 70);
            ctx.fillText('Δz', (dz_start + dz_end) / 2 - 10, bs_y + 95);


            // --- Draw Interference Pattern ---
            const pattern_r = 50;
            // Axes for pattern
            ctx.save();
            ctx.setLineDash([5, 5]);
            ctx.lineWidth = 1;
            ctx.beginPath();
            ctx.moveTo(pattern_cx - pattern_r - 20, pattern_cy);
            ctx.lineTo(pattern_cx + pattern_r + 20, pattern_cy);
            ctx.moveTo(pattern_cx, pattern_cy - pattern_r - 20);
            ctx.lineTo(pattern_cx, pattern_cy + pattern_r + 20);
            ctx.stroke();
            ctx.restore();

            // Axis labels for pattern
            ctx.fillText('y', pattern_cx - 10, pattern_cy - pattern_r - 25);
            ctx.beginPath();
            drawArrow(ctx, pattern_cx, pattern_cy - pattern_r - 12, pattern_cx, pattern_cy - pattern_r - 22, 8);
            ctx.stroke();
            ctx.fillText('x', pattern_cx + pattern_r + 25, pattern_cy + 7);
            ctx.beginPath();
            drawArrow(ctx, pattern_cx + pattern_r + 12, pattern_cy, pattern_cx + pattern_r + 22, pattern_cy, 8);
            ctx.stroke();
            
            // Fringes
            ctx.save();
            ctx.beginPath();
            ctx.arc(pattern_cx, pattern_cy, pattern_r, 0, 2 * Math.PI);
            ctx.fillStyle = '#e0e0e0';
            ctx.fill();
            ctx.clip(); // Clip to the circle
            
            ctx.lineWidth = 8;
            ctx.strokeStyle = 'black';
            for (let i = -2; i <= 2; i++) {
                const y_pos = pattern_cy + i * 18;
                ctx.beginPath();
                ctx.moveTo(pattern_cx - pattern_r, y_pos);
                ctx.lineTo(pattern_cx + pattern_r, y_pos);
                ctx.stroke();
            }
            ctx.restore();
            
            // Outline of the circle
            ctx.beginPath();
            ctx.lineWidth = 1.5;
            ctx.arc(pattern_cx, pattern_cy, pattern_r, 0, 2 * Math.PI);
            ctx.stroke();
        }

        drawDiagram();
    </script>
</body>
</html>